#include "DriverLoader.h"

CDriverLoader::CDriverLoader()
{
	schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);	// Local machine, default database 
}
// ---------------------------------------------------------------------- 

DWORD CDriverLoader::InstallDriver(IN LPCWSTR DriverName, IN LPCWSTR ServiceExe)
{
	SC_HANDLE schService;
	err = Successfull;

	schService = CreateService(schSCManager, DriverName, DriverName, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, ServiceExe, NULL, NULL, NULL, NULL, NULL);

	if (schService == NULL)
	{
		err = GetLastError();
	}

	CloseServiceHandle(schService);

	return err;
}
// ---------------------------------------------------------------------- 

DWORD CDriverLoader::RemoveDriver(IN LPCWSTR DriverName)
{
	SC_HANDLE schService;
	err = Successfull;

	schService = OpenService(schSCManager, DriverName, SERVICE_ALL_ACCESS);

	if (schService == NULL)
	{
		err = GetLastError();
		return err;
	}

	if (!DeleteService(schService))
	{
		err = GetLastError();
	}

	CloseServiceHandle(schService);

	return err;
}
// ---------------------------------------------------------------------- 

DWORD CDriverLoader::StartDriver(IN LPCWSTR DriverName)
{
	SC_HANDLE schService;
	err = Successfull;
	
	schService = OpenService(schSCManager, DriverName, SERVICE_ALL_ACCESS);

	if (schService == NULL)
	{
		err = GetLastError();
		return err;
	}

	if (!StartService(schService, 0, NULL))
	{
		err = GetLastError();
	}

	CloseServiceHandle(schService);

	return err;
}
// ---------------------------------------------------------------------- 

DWORD CDriverLoader::StopDriver(IN LPCWSTR DriverName)
{
	SC_HANDLE schService;
	SERVICE_STATUS	serviceStatus;
	err = Successfull;

	schService = OpenService(schSCManager, DriverName, SERVICE_ALL_ACCESS);

	if (schService == NULL)
	{
		err = GetLastError();
		return err;
	}

	if (!ControlService(schService, SERVICE_CONTROL_STOP, &serviceStatus))
	{
		err = GetLastError();
	}

	CloseServiceHandle(schService);

	return err;
}
// ---------------------------------------------------------------------- 

DWORD CDriverLoader::OpenDevice(HANDLE* pDeviceHandle, IN LPCWSTR DriverName)
{
	WCHAR completeDeviceName[64] = L"";
	err = Successfull;

	wcscat(completeDeviceName, L"\\\\.\\");
	wcscat(completeDeviceName, DriverName);
	*pDeviceHandle = CreateFile(completeDeviceName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	if (*pDeviceHandle ==((HANDLE)-1))
	{
		err = GetLastError();
	}

	return err;
}
// ---------------------------------------------------------------------- 

DWORD CDriverLoader::RegisterDriver(IN LPCWSTR DriverName, IN LPCWSTR ServiceExe)
{
	SC_HANDLE schService;

	err = Successfull;
	err = InstallDriver(DriverName, ServiceExe);

	if (!err)
	{
		return err;
	}

	err = StartDriver(DriverName);
	
	if (!err)
	{
		UnRegisterDriver(DriverName);
	}

	return err;
}
// ---------------------------------------------------------------------- 

DWORD CDriverLoader::UnRegisterDriver(IN LPCWSTR DriverName)
{
	SC_HANDLE schService;

	err = Successfull;
	err = StopDriver(DriverName);

	if (!err)
	{
		return err;
	}

	err = RemoveDriver(DriverName);

	return err;
}
// ---------------------------------------------------------------------- 

wstring CDriverLoader::GetLastDriverError()
{
	wstring wsError = L"";

	if (err == 0)
	{
		wsError = L"Last operation was successfull!";
	}
	else
	{
		LPVOID lpMsgBuf;

		FormatMessage(
			FORMAT_MESSAGE_ALLOCATE_BUFFER | 
			FORMAT_MESSAGE_FROM_SYSTEM |
			FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			err,
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			(LPWSTR) &lpMsgBuf,
			0, NULL );

		WCHAR wErr[128] = L"";
		wsprintf(wErr, L"%s", lpMsgBuf); 
		wsError.append(&wErr[0], wcslen(wErr) - 3);
		LocalFree(lpMsgBuf);
	}

	return wsError;
}
// ---------------------------------------------------------------------- 

CDriverLoader::~CDriverLoader()
{
	CloseServiceHandle(schSCManager);
}
// ---------------------------------------------------------------------- 
